#include "syscall.h"
typedef int bool;

#define true 1
#define false 0
#define NULL 0

#define MAX_CRNum 3 
#define MAX_ClerkNum 3
#define MAX_StockBoyNum 3
#define MAX_CustomerNum 20

#define MinPrice 1
#define PriceFactor 100

/*Environment Varible*/
int CRNum;
int ClerkNum;
int StockBoyNum;
int CustomerNum;
#define AisleNum 5
#define ItemNum 10

/*Tricks*/
/*These Varibles is used to create specific scenario for test cases*/
int ReturnChance;					/*The chance if a customer to be return customer*/
int LostChance;						/*The chance a customer fails to find an item*/
int OriginItemAmount;					/*Origin Amount of each Item*/
int MinBoughtEach;					/*Min number of items a customer can buy*/
int MaxBoughtEach;					/*Max number of items a customer can buy is [MinBoughtEach+MaxBoughtEach-1]*/
int BornLazy;						/*If a clerk will go to rest as soon as he is created?*/
/*int PriceFactor;*/					/*The Factor that affects randomly generated prices*/
/*int MinPrice;*/						/*The Mininum price can be generated*/
bool ManagerTrackLine;					/*Does Manager keep track of Line himself*/
bool CustomerBusyWaiting;
int ProgramRun;
int TotalSales;						/*record the total sales amount.*/

/*Locks*/
int initLock;
int idLock;							/*Lock to pretect id from race condition*/
int OpLock1;							/*StartLine Exclusion*/
int OpLock2;							/*StockBoy Break Exclusion*/
int OpLock3;							/*Clerk Break Exclusion*/
int OpLock4;							/*Leaving Customer Exclusion*/
int OpLock5;							/*For StockRoom Condition Check	*/
int TableLock[MAX_CRNum];				/*Acquire this Lock before handle items on table*/
int CheckQueue;							/*Acquire this lock before check Line Lengths*/
int ScreenLock[MAX_CRNum];				/*Acquire this Lock before interact with cash register machine*/
int StockRoomLock;						/*The Lock on StockRoom*/
int ServiceButtonLock;					/*The Lock to protect service button*/
int ClerkCallLock;						/*The Lock to protect clerk call flag*/
int StockBoyStatusLock;					/*The Lock to protect Stock Boy Status*/
int AisleHelpLock[AisleNum];		/*The Lock to protect AisleHelp related monitor varibles*/
int AisleLock[AisleNum];			/*Acquire this Lock before access any item on an aisle*/
int ServiceStateLock[MAX_StockBoyNum];	/*The Lock to protect help state between a stock boy and a customer*/

/*CVs*/
int StartLine;							/*the start line*/
int ClerkOnBreak;						/*The Condition that clerks on break wait on*/
int StockBoyOnBreak;					/*The Condition that stockboys on break wait on*/
int Queue[MAX_CRNum];					/*Paying Lines*/
int Screen[MAX_CRNum];					/*The cash register machine screen State Condition*/
int Table[MAX_CRNum];					/*The Cashier Table State Condition*/
int LackMoney[MAX_CRNum];				/*If a cash register lacks money to pay return customer, he waits for Manager here*/
int StockRoomCV;						/*The Condition on which Stock Boy wait for room*/
int WaitForRestockCV[ItemNum];		/*Customers waiting for item to be restocked. It is protected by AisleLock*/
int ServiceStateCV[MAX_StockBoyNum];	/*The State Condition when a stock boy is helping a customer*/
int AisleHelpCV[AisleNum];			/*The Condition a customer waits on before a stock boy comes to serve him*/
/*Synchronization Define End*/

/*Shared Varible End*/
int AisleNeedRestock;	/*record if an aisle need to be restocked*/
int ServiceButtonOn;	/*false*/
			/*If somebody pressed service button?*/
int ClerkCall;  	/*false;*/					/*If somebody ask for more clerk?*/
int ClerkCallId;					/*The Clerk who asked manager to wake another clerk*/

int QueueLength;			/*Lengths of paying Lines*/
int ClerkOnWork;			/*If a Clerk is ready for customer?*/
		
int TableArea;				/*Place to put items*/
int CashArea;				/*Place to put money*/

int data;				/*The data is the place to exchange information with cash register*/
int MoneyCollected;			/*The money each cash register earned before manager empty it*/
int TotalMoneyCollected;		/*The money each cash register ever earned*/
int MoneyLacked;			/*The money a cash register lacks to pay a return customer*/

int StockBoyInRoom;			/*Id of StockBoy currently in Stock Room*/

int StockBoyStatus;			/*Each StockBoy's status.If he is in an aisle, status is the aisle number or aisle+AisleNum; Otherwise,  -1*/
int AisleHelpLineLength;		/*The number of customer waiting for help on each aisle*/
int Booklet;				/*The booklet used by Customer and StockBoy to exchange information*/

int CustomerLeaving;			/*Total number of customers that finished shopping and left*/

int DidSomething;                        /*[MAX_StockBoyNum];*/
int Prices;
int ItemAmount;
int ItemRestockPrediction;

/*ID Assignment*/
int nextManagerID;
int nextCustomerID;
int nextClerkID;
int nextStockBoyID;
int nextCashRegisterID;

int CRNumIndex;
int ClerkNumIndex;
int StockBoyNumIndex;
int CustomerNumIndex;

int GenRandom(int limit)
{
	return Random(limit);
}

int modifyName(char * name, int offset, int num)
{
	int i=0;
	int pos=0;
	int digit;
	if(name == NULL) return -1;
	while(name[i]!='\0' && i<offset+4){
		i++;
	}
	if(name[i]=='\0' && i < offset+4) return -1;
	pos= i-1;
	while(num!=0){
		digit=num%10;
		num = (num-digit)/10;
		name[pos]=(char)(digit+48);
		pos--;
	}
	for(;pos>=offset;pos--)
		name[pos]='0';
	return 1;
}

void initialize()
{
	char* name;
	int numbers[6];
	int i;
		
	nextManagerID = CreateMV("nextManagerID",13,1,0);
	nextCustomerID = CreateMV("nextCustomerID",14,1,0);
	nextClerkID = CreateMV("nextClerkID",11,1,0);
	nextStockBoyID = CreateMV("nextSBID",14,1,0);
	nextCashRegisterID = CreateMV("nextCRID",18,1,0);

	numbers[0] = CRNumIndex = CreateMV("CRNum",5,1,MAX_CRNum);
	numbers[1] = ClerkNumIndex = CreateMV("ClerkNum",8,1,MAX_ClerkNum);
	numbers[2] = StockBoyNumIndex = CreateMV("StockBoyNum",11,1,MAX_StockBoyNum);
	numbers[3] = CustomerNumIndex = CreateMV("CustomerNum",11,1,MAX_CustomerNum);
	
	WriteFormat("Index: CR %d Clerk %d StockBoy %d Customer %d \n",48,numbers,4);

	CRNum = GetMV(CRNumIndex,0);
	ClerkNum = GetMV(ClerkNumIndex,0);
	StockBoyNum = GetMV(StockBoyNumIndex,0);
	CustomerNum = GetMV(CustomerNumIndex,0);	

	OpLock1 = RemoteCreateLock("OperationLock1",15); 		
	OpLock2 = RemoteCreateLock("OperationLock2",15);
	OpLock3 = RemoteCreateLock("OperationLock3",15);
	OpLock4 = RemoteCreateLock("OperationLock4",15);
	OpLock5 = RemoteCreateLock("OperationLock5",15);
	idLock= RemoteCreateLock("IDLock",7);
	StartLine =  RemoteCreateCondition("StartLine",10);
	ClerkOnBreak =  RemoteCreateCondition("ClerkBreak",11);
	StockBoyOnBreak =  RemoteCreateCondition("StockBoyBreak",14);
	CheckQueue = RemoteCreateLock("CheckQueueLock",15);
	StockRoomLock = RemoteCreateLock("StockRoomLock",14);
	StockRoomCV = RemoteCreateCondition("StockRoomCV",12);
	ServiceButtonLock = RemoteCreateLock("ServiceButtonLock",18);
	StockBoyStatusLock = RemoteCreateLock("StockBoyStatusLock",19);
	ClerkCallLock=RemoteCreateLock("ClerkCallLock",14);

	/*MV initialize*/
	ReturnChance = CreateMV("ReturnChance",12,1,20);	/*The chance if a customer to be return customer*/
	LostChance = CreateMV("LostChance",10,1,25);		/*The chance a customer fails to find an item*/
	OriginItemAmount = CreateMV("OriginItemAmount",16,1,3);	/*Origin Amount of each Item*/
	MinBoughtEach = CreateMV("MinBoughtEach",13,1,1);	/*Min number of items a customer can buy*/
	MaxBoughtEach = CreateMV("MaxBoughtEach",13,1,10);	/*Max number of items a customer can buy is [MinBoughtEach+MaxBoughtEach-1]*/
	/*PriceFactor = CreateMV("PriceFactor",11,1,100);*/		/*The Factor that affects randomly generated prices*/
	/*MinPrice = CreateMV("MinPrice",8,1,0);*/			/*The Mininum price can be generated*/
	ManagerTrackLine = CreateMV("ManagerTrackLine",16,1,true);/*Does Manager keep track of Line himself*/
	
	ProgramRun=CreateMV("ProgramRun",10,1,true);
	TotalSales=CreateMV("TotalSales",10,1,0);
	CustomerBusyWaiting = CreateMV("CustomerBusyWaiting",19,1,false);
	ServiceButtonOn=CreateMV("ServiceButtonOn",15,1,0);
	ClerkCall=CreateMV("ClerkCall",9,1,0);
	ClerkCallId=CreateMV("ClerkCallId",11,1,-1);
    StockBoyInRoom=CreateMV("StockBoyInRoom",14,1,-1);
    CustomerLeaving=CreateMV("CustomerLeaving",15,1,0);
	
	/*For CR-related MV*/
	QueueLength=CreateMV("QueueLength",11,CRNum,0);
	ClerkOnWork=CreateMV("ClerkOnWork",11,CRNum,1);
	BornLazy=CreateMV("BornLazy",8,CRNum,0);
	TableArea=CreateMV("TableArea",9,CRNum,-1);	
	CashArea=CreateMV("CashArea",8,CRNum,0);
	data=CreateMV("data",4,CRNum,-1);			/*-1 is used to denote initial state for cash register*/
	MoneyCollected=CreateMV("MoneyCollected",14,CRNum,0);
	TotalMoneyCollected=CreateMV("TotalMoneyCollected",19,CRNum,0);
	MoneyLacked=CreateMV("MoneyLacked",11,CRNum,-1);

	/*For stockboy-related MV*/
	Booklet = CreateMV("Booklet",7,StockBoyNum,-1);	
	StockBoyStatus = CreateMV("StockBoyStatus",14,StockBoyNum,-1);/*StockBoyStatus == -1 means he is out of any aisle*/
	DidSomething=CreateMV("DidSomething",12,StockBoyNum,false);

	/*For aisle-related MV*/
	AisleNeedRestock=CreateMV("AisleNeedRestock",16,AisleNum,0);	/*no aisle need to be restocked at very beginning*/
	AisleHelpLineLength=CreateMV("AisleHelpLineLength",19,AisleNum,0);/*originally no customer is waiting for help in any aisle*/
	/*Initialization of array varibles declared*/

	/*For item-related MV*/
	Prices=CreateMV("Prices",6,ItemNum,0);
	ItemRestockPrediction=CreateMV("ItemRestockPrediction",21,ItemNum,0);/*Item to be restocked is 0	*/
	ItemAmount = CreateMV("ItemAmount",10,ItemNum,3);	/*Origin Amount of each Item*/
	
	for(i=0;i<CRNum;i++)
	{
		/*char* name;*/
		name="Queue0000";
		modifyName(name,5,i);	
		Queue[i] = RemoteCreateCondition(name,9);
		
		name="TableLock0000";
		modifyName(name,9,i);
		TableLock[i]=RemoteCreateLock(name,13);
		
		name="Table0000";
		modifyName(name,5,i);
		Table[i]=RemoteCreateCondition(name,9);
		
		name="ScreenLock0000";
		modifyName(name,10,i);
		ScreenLock[i]=RemoteCreateLock(name,14);
			
		name="Screen0000";
		modifyName(name,6,i);
		Screen[i]=RemoteCreateCondition(name,10);
		
		name="Lack0000";
		modifyName(name,4,i);
		LackMoney[i]=RemoteCreateCondition(name,8);
	}

	for(i=0;i<StockBoyNum;i++)
	{
		name="ServiceStateLock0000";
		modifyName(name,16,i);
		ServiceStateLock[i]=RemoteCreateLock(name,20);
		
		name="ServiceState0000";
		modifyName(name,12,i);
		ServiceStateCV[i]=RemoteCreateCondition(name,16);
	}

	for (i=0;i<AisleNum;i++)
	{
		name="AisleHelpLock0000";
		modifyName(name,13,i);
		AisleHelpLock[i]=RemoteCreateLock(name,17);
		
		name="AisleHelpCV0000";
		modifyName(name,11,i);
		AisleHelpCV[i]=RemoteCreateCondition(name,15);
		
		name="AisleLock0000";
		modifyName(name,9,i);
		AisleLock[i]=RemoteCreateLock(name,13);
	}
	
	for(i=0;i<ItemNum;i++)
	{
		name="WaitForRestockCV0000";
		modifyName(name,16,i);
		WaitForRestockCV[i]=RemoteCreateCondition(name,20);
	}
}

void initializeEnvironment()
{
	char* name;
	int  numbers[6];
	int i,j;

	i = CreateMV("ManagerState",12,1,0);
	j = GetMV(i,0);
	if(j==0)
		SetMV(i,0,1);
	else
	{
		WriteFormat("ERROR ! Only ONE instance of Manager can run at a time\n",56,0,0);
		Exit(0);
	}
	
	Write("============================================\n", 45, 1);
	Write("         Home Depot Store Simulation        \n\n", 46 ,1);
	Write("          part2 of project1,CSCI402         \n", 45 ,1);
	Write("                  Group#11                  \n", 45 ,1);
	Write("============================================\n\n", 46 ,1);

	WriteFormat("Hello Manager!!\n\n",19,0,0);	
	
	numbers[0] = i = CreateMV("CRNum",5,1,MAX_CRNum);
	numbers[1] = j = ReadInput("How many Clerk do you want to hire?",35);
	SetMV(i,0,j);
	WriteFormat("Set %d with %d \n",17,numbers,2);

	numbers[0] = i = CreateMV("ClerkNum",8,1,MAX_ClerkNum);
	SetMV(i,0,j);
	WriteFormat("Set %d with %d \n",17,numbers,2);

	numbers[0] = i = CreateMV("StockBoyNum",11,1,MAX_StockBoyNum);
	numbers[1] = j = ReadInput("How many StockBoy do you want to hire?",38);
	SetMV(i,0,j);
	WriteFormat("Set %d with %d \n",17,numbers,2);

	numbers[0] = i = CreateMV("CustomerNum",11,1,MAX_CustomerNum);
	numbers[1] = j = ReadInput("How many Customer do you want to serve?",39);
	SetMV(i,0,j);
	WriteFormat("Set %d with %d \n",17,numbers,2);

	CRNum = GetMV(CreateMV("CRNum",5,1,MAX_CRNum),0);
	ClerkNum = GetMV(CreateMV("ClerkNum",8,1,MAX_ClerkNum),0);
	StockBoyNum = GetMV(CreateMV("StockBoyNum",11,1,MAX_StockBoyNum),0);
	CustomerNum = GetMV(CreateMV("CustomerNum",11,1,MAX_CustomerNum),0);	

	Prices=CreateMV("Prices",6,ItemNum,0);
	for(i=0;i<ItemNum;i++)
		SetMV(Prices,i, MinPrice+1+GenRandom(PriceFactor));		/*generate price*/
	
	Write("================ Program Start =============\n",45,1);	/*Simulation Start*/
	numbers[0] = ClerkNum;
	WriteFormat("Number of Clerks = [%d]\n",25, numbers,1);				/*print as sample out put*/
	numbers[0] = StockBoyNum;
	WriteFormat("Number of StockBoys = [%d]\n",28, numbers,1);
	numbers[0] = CRNum;
	WriteFormat("Number of CashRegisters = [%d]\n",32,numbers,1);
	numbers[0] = CustomerNum;
	WriteFormat("Number of Customers = [%d]\n",28, numbers,1);
	numbers[0] = 1;
	WriteFormat("Number of Managers = [%d]\n",27,numbers,1);
	numbers[0] = AisleNum;
	WriteFormat("Number of Aisles = [%d]\n",25, numbers,1);
	Write("	Items:\n", 8, 1);
	Write("		Number - Price\n", 17, 1);
	for(i=0;i<ItemNum;i++){
		numbers[0]=i;
		numbers[1]=GetMV(Prices,i)/10;
		numbers[2]=GetMV(Prices,i)%10;
		WriteFormat("		[%d] - $[%d.%d]\n",19,numbers,3);
	}
}


/*---------------------Manager Minor----------------------*/
/*	Minor Behaviors of Manager*/
/*	Lots of synchronization involved*/
/*	by Momo*/
/*--------------------------------------------------------*/

void TakeTime(int time)											/*take time to do something*/
{
	int i;
	int sum = 0;
	for(i=0;i<time * 100;i++)
		sum+=i;
}


void
ManagerIdle()													/*Manager do this between tasks*/
{
	TakeTime(50);
}

void 
WakeUpCustomer()												/*wake up customers*/
{
	RemoteAcquireLock(OpLock1);
	RemoteBroadcastCondition(StartLine,OpLock1);
	RemoteReleaseLock(OpLock1);
}

void
TurnOffMachine()
{
	int i,j;
	for (i=0;i<CRNum;i++)
	{
		RemoteAcquireLock(ScreenLock[i]);
		SetMV(data,i,-100);
		RemoteSignalCondition(Screen[i],ScreenLock[i]);
		RemoteReleaseLock(ScreenLock[i]);
	}
}

void 
CollectCash()													/*Manager collect cash from register machines*/
{
	int numbers[3];
	int i,j;
	for (i=0;i<CRNum;i++)
	{
		int lacked;
		
		TakeTime(2);									/*It takes some time to collect cash from machine*/
		
		RemoteAcquireLock(ScreenLock[i]);								/*Acquire cash register's lock*/
		
		lacked = GetMV(MoneyLacked,i);							/*Read register information*/
		if(lacked>0)											/*if this register is needing money*/
		{
			SetMV(MoneyCollected,i,0-lacked);	/*TotalSales -= lacked;	//provide money to this cash reg*/
			SetMV(MoneyLacked,i,-1);									/*reset data*/
			
			RemoteSignalCondition(LackMoney[i],ScreenLock[i]);				/*tell that cash register I have provided money*/
			numbers[0]=lacked/10;
			numbers[1]=lacked%10;
			numbers[2]=i;
			WriteFormat("Manager gave $[%d.%d] to cash register [%d].\n",49,numbers,3);
		}
		SetMV(TotalSales,0,GetMV(TotalSales,0)+GetMV(MoneyCollected,i));							/*Collect money, add to total sales			*/
		SetMV(TotalMoneyCollected,i, GetMV(TotalMoneyCollected,i) + GetMV(MoneyCollected,i));				/*Count total sales of eace cash register*/
		
		numbers[0]=i;
		WriteFormat("Cash Register [%d] drawer is emptied by Manager.\n",50,numbers,1);
		
		numbers[1]= GetMV(MoneyCollected,i)/10;
		numbers[2]= abs(GetMV(MoneyCollected,i)%10);
		WriteFormat("Cash Register [%d] total sale until now is $[%d.%d].\n",57, numbers,3);	/*Professor crowley says it is OK*/
		
		WriteFormat("Manager emptied Cash Register [%d] drawer.\n",44,numbers,1);
		
		numbers[0]=GetMV(TotalSales,0)/10;
		numbers[1]=abs(GetMV(TotalSales,0)%10);
		WriteFormat("Manager has total sale of $[%d.%d].\n", 40,numbers,2);
		SetMV(MoneyCollected,i,0);									/*Empty cash reg balance*/
		RemoteReleaseLock(ScreenLock[i]);								/*Release lock*/
	}

	if(GenRandom(100)<50)										/*Randomly print out this statement*/
	{
		numbers[0]=GetMV(TotalSales,0)/10;
		numbers[1]=abs(GetMV(TotalSales,0)%10);
		WriteFormat("-------Total Sale of the entire store until now is $[%d.%d]-------\n",71, numbers,2);
	}
}
/*---------------------Manager Major----------------------*/
/*Manager Behavior*/
/*	the main Logic of the Manager*/
/*by Momo*/
/*--------------------------------------------------------*/

void
ManagerBehavior()
{
	int id;
	int numbers[6];
	int i,j,k;

/*****************************
 *      Be Careful !!!!      *
 * Should be Only One Manager*
 *****************************/

	RemoteAcquireLock(idLock);	
	id=GetMV(nextManagerID,0);
	SetMV(nextManagerID,0,id+1);
	RemoteReleaseLock(idLock);

	while(true)
	{	
		WriteFormat("Manager Running...\n",20,0,0);

		ManagerIdle();

		RemoteAcquireLock(ClerkCallLock);								/*check if there is a call for clerk*/
		if (GetMV(ClerkCall,0))
		{
			if(GetMV(ClerkCallId,0)!=-1)									/*if clerk call id is -1, it is from customer, otherwise, print clerk id*/
			{
				numbers[0]=GetMV(ClerkCallId,0);
				WriteFormat("Manager got a call from Clerk [%d].\n",37,numbers,1);
				SetMV(ClerkCallId,0,-1);
			}
			
			RemoteAcquireLock(OpLock3);
			
			RemoteSignalCondition(ClerkOnBreak,OpLock3);						/*wake up one clerk*/
			Write("Manager wakes up Clerk.\n",24,1);
			
			RemoteReleaseLock(OpLock3);
			WakeUpCustomer();									/*wake up customers that may be waiting*/
			SetMV(ClerkCall,0,false);
			SetMV(ClerkCallId,0,-1);
		}
		
		
		RemoteReleaseLock(ClerkCallLock);
		
		ManagerIdle();

		for (j=0;j<AisleNum;j++)							/*Check if there is an aisle need restock*/
		{
			
			RemoteAcquireLock(AisleLock[j]);
			if (GetMV(AisleNeedRestock,j))							/*If there is*/
			{
				RemoteAcquireLock(OpLock2);
				RemoteBroadcastCondition(StockBoyOnBreak,OpLock2);			/*wake up all stockboys*/
				/*printf("Items missed in Aisle %d!!Manager call all the Stockboy to work!!\n",j);*/
				RemoteReleaseLock(OpLock2);
				RemoteReleaseLock(AisleLock[j]);
				break;
			}
			RemoteReleaseLock(AisleLock[j]);
		}

		ManagerIdle();

		RemoteAcquireLock(ServiceButtonLock);						/*check if service button is pressed*/
		if (GetMV(ServiceButtonOn,0))									/*if pressed*/
		{
			/*wake up all stock boys that are taking break;*/
			RemoteAcquireLock(OpLock2);
			
			RemoteBroadcastCondition(StockBoyOnBreak,OpLock2);				/*wake up all stockboys*/
			Write("Manager wakes up StockBoy.\n",27,1);
			
			RemoteReleaseLock(OpLock2);
			WakeUpCustomer();									/*wake up customers that may be waiting*/
			SetMV(ServiceButtonOn,0,false);
		}
		
		RemoteReleaseLock(ServiceButtonLock);

		ManagerIdle();

		CollectCash();											/*collect cash from each cash register*/

		ManagerIdle();
		
		if(GetMV(ManagerTrackLine,0))									/*Manager keep track of line lengths himself*/
		{
			RemoteAcquireLock(CheckQueue);
			
			/*Potential Bug!!!!!
			 Customer can wait on empty clerk!!!*/			
			for(k=0;k<CRNum;k++)
				if(GetMV(QueueLength,k)>0 && (!GetMV(ClerkOnWork,k)))		/*If there is a line on which people is waiting but no clerk work*/
					break;
			RemoteReleaseLock(CheckQueue);

			if(k!=CRNum)										/*such a line exist*/
			{													/*wake up a clerk*/
				RemoteAcquireLock(OpLock3);
				
				RemoteSignalCondition(ClerkOnBreak,OpLock3);
				Write("Manager wakes up Clerk.\n",24,1);
				
				RemoteReleaseLock(OpLock3);
				WakeUpCustomer();								/*wake up customer that may be waiting*/
				SetMV(ClerkCall,0,false);
			}
		}

	RemoteAcquireLock(OpLock4);										/*Check if all customers have left*/


		/*Re think about it!!!!!!!!!!!!!!!!
		  Does it have to be MV???  YES*/

		if (GetMV(CustomerLeaving,0)!=CustomerNum)
		{
			RemoteReleaseLock(OpLock4);
			continue;											/*if not ,continue*/
		}

		RemoteReleaseLock(OpLock4);

		
		/*Exiting Codes!										//Else, close store!*/

		SetMV(ProgramRun,0,false);
		/*printf("All customer leaves, program exit!!i\n");*/
	

		/*Wake up stockboy*/
		RemoteAcquireLock(OpLock2);
		RemoteBroadcastCondition(StockBoyOnBreak,OpLock2);			/*wake up all stockboys*/
		/*printf("Items missed in Aisle %d!!Manager call all the Stockboy to work!!\n",j);*/
		RemoteReleaseLock(OpLock2);
	
		/*Wake up clerk*/
		RemoteAcquireLock(OpLock3);
		RemoteBroadcastCondition(ClerkOnBreak,OpLock3);						/*wake up one clerk*/
		RemoteReleaseLock(OpLock3);
		
		/*WakeUpCustomer();*/									/*wake up customers that may be waiting*/
			
		CollectCash();											/*Collect cash for last time*/

		TurnOffMachine();

		/*printf("Total Sales: %0.1f\n",TotalSales);*/
		for (i=0;i<CRNum;i++)									/*Print Statictics*/
		{
			numbers[0]=i;
			numbers[1]=GetMV(TotalMoneyCollected,i)/10;
			numbers[2]=abs(GetMV(TotalMoneyCollected,i)%10);
			WriteFormat("Total Sale from Cash Register [%d] is $[%d.%d].\n",49,numbers,3);
		}
		
		numbers[0]=GetMV(TotalSales,0)/10;
		numbers[1]=abs(GetMV(TotalSales,0)%10);
		WriteFormat("Total Sale of the entire store is $[%d.%d].\n", 45, numbers,2);

		break;													/*Thread end*/
	}
	Exit(0);
}

int
main()
{
	initializeEnvironment();/*Specially designed for Manager, initialize environment varible*/
	initialize();		/*Generic Initialization function*/
	ManagerBehavior();
}
